package com.zadtek.sharkRider.util.gmap;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.location.Location;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityCompat;
import android.util.Log;
import android.widget.Toast;

import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.PendingResult;
import com.google.android.gms.common.api.ResultCallback;
import com.google.android.gms.common.api.Status;
import com.google.android.gms.location.LocationAvailability;
import com.google.android.gms.location.LocationListener;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.location.LocationSettingsRequest;
import com.google.android.gms.location.LocationSettingsResult;
import com.google.android.gms.location.LocationSettingsStatusCodes;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.model.LatLng;


public class GLocation implements GoogleApiClient.ConnectionCallbacks,GoogleApiClient.OnConnectionFailedListener,LocationListener{

    public static final String TAG = "GLocation";
    private int mZoom = 12;
    private GoogleMap mMap;
    private GoogleApiClient mGoogleApiClient;
    private LocationRequest mLocationRequest;
    private boolean mLocationUpdateState;
    private static final int REQUEST_LOCATION = 1;
    private static final int LOCATION_PERMISSION_REQUEST_CODE = 2;
    private static final int MSG_TIME_OUT = 3;
    private boolean mLocationSuccessful = false;
    private LocationManager mLocationManager;

    private Handler mHandler = new Handler(Looper.myLooper()){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            if (msg.what == MSG_TIME_OUT){
                failure("定位超时");
            }
        }
    };

    protected void successful(double lng,double lat){
        mLocationSuccessful = true;
        mHandler.removeMessages(MSG_TIME_OUT);
        Log.i(TAG,"location successful lng = "+lng+",lat = "+lat);
    }

    protected void failure(String msg){
        mLocationSuccessful = false;
        mHandler.removeMessages(MSG_TIME_OUT);
        Log.i(TAG,"location failure："+msg);
    }

    private Activity mActivity;
    public GLocation(Activity activity) {
        this.mActivity = activity;
        this.mLocationManager = (LocationManager) mActivity.getSystemService(Context.LOCATION_SERVICE);
        if (mGoogleApiClient == null) {
            mGoogleApiClient = new GoogleApiClient.Builder(mActivity)
                    .addConnectionCallbacks(this)
                    .addOnConnectionFailedListener(this)
                    .addApi(LocationServices.API)
                    .build();
        }
        createLocationRequest();
    }

    private void createLocationRequest() {
        mLocationRequest = new LocationRequest();
        mLocationRequest.setInterval(5000);
        mLocationRequest.setFastestInterval(3000);
        mLocationRequest.setSmallestDisplacement(0.1F);
        mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);

        LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder()
                .addLocationRequest(mLocationRequest);

        PendingResult<LocationSettingsResult> result =
                LocationServices.SettingsApi.checkLocationSettings(mGoogleApiClient,
                        builder.build());

        result.setResultCallback(new ResultCallback<LocationSettingsResult>() {
            @Override
            public void onResult(@NonNull LocationSettingsResult result) {
                final Status status = result.getStatus();
                switch (status.getStatusCode()) {
                    case LocationSettingsStatusCodes.SUCCESS:
                        mLocationUpdateState = true;
                        Log.i(TAG,"onResult SUCCESS");
                        location();
                        break;
                    case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
                        Log.i(TAG,"onResult RESOLUTION_REQUIRED");
                        try {
                            status.startResolutionForResult(mActivity, REQUEST_LOCATION);
                        }catch (Exception e){
                            e.printStackTrace();
                        }
                        break;
                    case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
                        Log.i(TAG,"onResult SETTINGS_CHANGE_UNAVAILABLE");
                        break;
                }
            }
        });
    }

    public void onMapReady(GoogleMap googleMap){
        this.mMap = googleMap;
        mMap.setIndoorEnabled(true);
        mMap.setMyLocationEnabled(true);
        mGoogleApiClient.connect();
    }

    public void onStart() {
        mGoogleApiClient.connect();
    }

    public void onResume() {
        if (mGoogleApiClient != null &&mGoogleApiClient.isConnected()) {
            location();
        }
    }

    public void onStop() {
        if( mGoogleApiClient != null && mGoogleApiClient.isConnected() ) {
            mGoogleApiClient.disconnect();
        }
    }

    public void onPause() {
        if(mGoogleApiClient.isConnected()){
            LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
        }
    }

    private void setUpMap() {
        if (requestPermissions()){
            return;
        }

        LocationAvailability locationAvailability = LocationServices.FusedLocationApi.getLocationAvailability(mGoogleApiClient); // 2
        if (null != locationAvailability && locationAvailability.isLocationAvailable()) {
            Location location = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
            Log.i(TAG, "setUpMap ：locationAvailability = true");
            if (location != null) {
                Log.i(TAG, "setUpMap ：lng = " + location.getLongitude() + ",lat = " + location.getLatitude());
                successful(location.getLongitude(),location.getLatitude());
                LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude());
//                MapsInitializer.initialize(mActivity);
//                mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(latLng, mZoom));
            }
        }else {
            androidLocation();
            //failure("定位不可用");
            Log.i(TAG, "setUpMap ：locationAvailability = false");
        }
    }

    public void location() {
        Log.i(TAG,"location");
        if (requestPermissions()){
            return;
        }
        mHandler.removeMessages(MSG_TIME_OUT);
        mHandler.sendEmptyMessageDelayed(MSG_TIME_OUT,60*1000);

        if (mGoogleApiClient.isConnected()){
            Log.i(TAG,"location GoogleApiClient connected");
            LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
        }else {
            mGoogleApiClient.connect();
            Log.i(TAG,"location GoogleApiClient unconnected");
        }
    }

    public void remove(){
        LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient,this);
        mGoogleApiClient.disconnect();
    }

    private boolean requestPermissions(){
        if (ActivityCompat.checkSelfPermission(mActivity, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
                && ActivityCompat.checkSelfPermission(mActivity, android.Manifest.permission.ACCESS_COARSE_LOCATION)
                != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(mActivity, new String[]{android.Manifest.permission.ACCESS_FINE_LOCATION,android.Manifest.permission.ACCESS_COARSE_LOCATION}, LOCATION_PERMISSION_REQUEST_CODE);
            return true;
        }

        return false;
    }

    public boolean isSuccessful(){
        return mLocationSuccessful;
    }

    public void setZoom(int zoom){
        this.mZoom = zoom;
    }

    @Override
    public void onLocationChanged(Location location) {
        mHandler.removeMessages(MSG_TIME_OUT);
        if (location !=null) {
            Log.i(TAG, "onLocationChanged ：lng = " + location.getLongitude() + ",lat = " + location.getLatitude());
        }else {
            Log.i(TAG, "location failure,because location is null!");
        }
    }

    @Override
    public void onConnected(@Nullable Bundle bundle) {
        Log.i(TAG,"onConnected");
        setUpMap();
        location();
    }

    @Override
    public void onConnectionSuspended(int i) {
        Log.i(TAG,"onConnectionSuspended");
        failure("连接被断开");
    }

    @Override
    public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
        Log.i(TAG,"onConnectionFailed");
        failure("连接失败");
    }

    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == REQUEST_LOCATION && resultCode == Activity.RESULT_OK){
            mLocationUpdateState = true;
            location();
        }
    }
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        if (requestCode == LOCATION_PERMISSION_REQUEST_CODE){
            if (grantResults.length >0){
                onResume();
            }else {
                failure("无定位权限");
            }
        }
    }

    /**Android location*/
    private android.location.LocationListener mLocationListener = new android.location.LocationListener() {
        @Override
        public void onLocationChanged(Location location) {
            if (location != null) {
                Log.i(TAG,"Android 定位成功，onLocationChanged："+location.toString());
                successful(location.getLongitude(),location.getLatitude());
            } else {
                Toast.makeText(mActivity, AddressService.ERROR_GOOGLE_SERVICE_INVALID,Toast.LENGTH_SHORT).show();
                Log.i(TAG,"Location is null");
            }
        }

        @Override
        public void onStatusChanged(String s, int i, Bundle bundle) {
        }

        @Override
        public void onProviderEnabled(String s) {
        }

        @Override
        public void onProviderDisabled(String s) {
            Toast.makeText(mActivity, s,Toast.LENGTH_SHORT).show();
        }
    };

    private void androidLocation() {
        Log.i(TAG,"使用Android 内置定位");
        boolean isGPSEnabled = mLocationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
        boolean isNetworkEnabled = mLocationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);

        Location location = null;

        if (isNetworkEnabled) {
            Log.i(TAG,"使用Android 网络定位");
            mLocationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,
                    1000, 500, mLocationListener);
            location = mLocationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
        }else if (isGPSEnabled) {
            Log.i(TAG,"使用Android GPS定位");
            mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,
                    1000, 500, mLocationListener);
            location = mLocationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
        }

        if (location != null){
            Log.i(TAG,"Android 定位成功，获取已知定位信息："+location.toString());
            successful(location.getLongitude(),location.getLatitude());
        }
    }
}
